using System;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using RTMP.SimpleClient.ValueObject;
using RTMP.SimpleClient.Helpers;
using RTMP.SimpleClient.Exceptions;
using RTMP.SimpleClient.MessageReceiver;
using RTMP.SimpleClient.Callbacks;
using RTMP.SimpleClient.Messages;

namespace RTMP.SimpleClient
{
    /// <summary>
    /// RTMP 客户端状态枚举
    /// </summary>
    public enum RTMPClientState
    {
        /// <summary>
        /// 未连接状态
        /// </summary>
        Disconnected,

        /// <summary>
        /// 正在连接状态
        /// </summary>
        Connecting,

        /// <summary>
        /// 已连接状态
        /// </summary>
        Connected,

        /// <summary>
        /// 正在流式传输状态
        /// </summary>
        Streaming,

        /// <summary>
        /// 正在断开连接状态
        /// </summary>
        Disconnecting,

        /// <summary>
        /// 错误状态
        /// </summary>
        Error
    }

    /// <summary>
    /// 简单的 RTMP 客户端实现（有限状态机）
    /// </summary>
    public class RTMPSimpleClient : IRTMPClient, IDisposable
    {
        private TcpClient? _tcpClient;
        private NetworkStream? _networkStream;
        private uint _nextStreamId = 1;
        private double _nextTransactionId = 1.0;
        private RTMPClientState _currentState = RTMPClientState.Disconnected;
        private readonly object _stateLock = new object();
        private readonly object _transactionLock = new object();

        // 消息接收和回调管理组件
        private IMessageReceiver? _messageReceiver;
        private CallbackManager? _callbackManager;
        private IMessageConverter _messageConverter;
        private readonly object _componentsLock = new object();

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="messageConverter">消息转换器（可选）</param>
        public RTMPSimpleClient(IMessageConverter? messageConverter = null)
        {
            _messageConverter = messageConverter ?? new DefaultMessageConverter();
        }

        /// <summary>
        /// 获取当前状态
        /// </summary>
        public RTMPClientState CurrentState
        {
            get
            {
                lock (_stateLock)
                {
                    return _currentState;
                }
            }
        }

        /// <summary>
        /// 获取回调管理器
        /// </summary>
        public CallbackManager? CallbackManager
        {
            get
            {
                lock (_componentsLock)
                {
                    return _callbackManager;
                }
            }
        }

        /// <summary>
        /// 线程安全地更改状态
        /// </summary>
        /// <param name="newState">新状态</param>
        private void ChangeState(RTMPClientState newState)
        {
            lock (_stateLock)
            {
                _currentState = newState;
            }
        }

        /// <summary>
        /// 验证状态转换是否有效
        /// </summary>
        /// <param name="expectedState">期望的当前状态</param>
        /// <param name="operation">操作名称</param>
        private void ValidateState(RTMPClientState expectedState, string operation)
        {
            lock (_stateLock)
            {
                if (_currentState != expectedState)
                {
                    throw new RTMPInvalidStateException($"Cannot {operation} in state {_currentState}. Expected state: {expectedState}");
                }
            }
        }

        /// <summary>
        /// 检查是否可以执行连接操作
        /// </summary>
        private void ValidateCanConnect()
        {
            lock (_stateLock)
            {
                if (_currentState != RTMPClientState.Disconnected)
                {
                    throw new RTMPInvalidStateException($"Cannot connect in state {_currentState}. Client must be disconnected.");
                }
            }
        }

        /// <summary>
        /// 检查是否可以执行流操作
        /// </summary>
        private void ValidateCanStream()
        {
            lock (_stateLock)
            {
                if (_currentState != RTMPClientState.Connected && _currentState != RTMPClientState.Streaming)
                {
                    throw new RTMPInvalidStateException($"Cannot perform stream operation in state {_currentState}. Client must be connected.");
                }
            }
        }

        /// <summary>
        /// 检查是否可以执行断开操作
        /// </summary>
        private void ValidateCanDisconnect()
        {
            lock (_stateLock)
            {
                if (_currentState == RTMPClientState.Disconnected)
                {
                    throw new RTMPInvalidStateException("Client is already disconnected.");
                }
            }
        }

        /// <summary>
        /// 异步连接到 RTMP 服务器
        /// </summary>
        /// <param name="url">RTMP 服务器 URL</param>
        /// <param name="options">可选的连接选项</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>连接任务</returns>
        public async Task ConnectAsync(string url, RTMPConnectOptions? options = null, CancellationToken cancellationToken = default)
        {
            ValidateCanConnect();
            ChangeState(RTMPClientState.Connecting);

            try
            {
                // 解析 URL
                var uri = new Uri(url);
                if (uri.Scheme != "rtmp")
                {
                    throw new RTMPConnectionException("Invalid RTMP URL scheme.");
                }

                string host = uri.Host;
                int port = uri.Port == -1 ? 1935 : uri.Port;

                // 建立 TCP 连接
                _tcpClient = new TcpClient();
                await _tcpClient.ConnectAsync(host, port, cancellationToken);
                _networkStream = _tcpClient.GetStream();

                // 执行 RTMP 握手
                await PerformHandshakeAsync(cancellationToken);

                // 发送 RTMP Connect 命令
                await PerformConnectAsync(uri, options, cancellationToken);

                // 初始化消息处理组件
                await InitializeMessageHandlingAsync(cancellationToken);

                ChangeState(RTMPClientState.Connected);
            }
            catch (Exception ex)
            {
                ChangeState(RTMPClientState.Error);
                await CleanupComponentsAsync();
                throw;
            }
        }

        private async Task PerformSetChunkSizeAsync(int chunkSize, CancellationToken cancellationToken)
        {
            if (_networkStream == null)
            {
                throw new RTMPConnectionException("Network stream is not available.");
            }

            var payload = RTMPChunkHelper.GetSetChunkSizePayload(chunkSize);
            await _networkStream.WriteAsync(payload, 0, payload.Length, cancellationToken);
        }

        /// <summary>
        /// 执行 RTMP 握手
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        private async Task PerformHandshakeAsync(CancellationToken cancellationToken = default)
        {
            if (_networkStream == null)
            {
                throw new RTMPConnectionException("Network stream is not available.");
            }

            await RTMPHandshakeHelper.PerformHandshakeAsync(_networkStream, cancellationToken);
        }

        /// <summary>
        /// 发送 RTMP Connect 命令并等待响应 (使用传统方式，避免消息解析问题)
        /// </summary>
        /// <param name="options">连接选项</param>
        /// <param name="uri">RTMP服务器URI</param>
        /// <param name="cancellationToken">取消令牌</param>
        private async Task PerformConnectAsync(Uri uri, RTMPConnectOptions? options, CancellationToken cancellationToken = default)
        {
            if (_networkStream == null)
                throw new InvalidOperationException("");

            // 从URI中提取app名称
            var appName = uri.AbsolutePath.TrimStart('/');
            if (string.IsNullOrEmpty(appName))
            {
                appName = "live"; // 默认应用名
            }

            // 构建完整的tcUrl
            var tcUrl = $"{uri.Scheme}://{uri.Host}:{(uri.Port == -1 ? 1935 : uri.Port)}/{appName}";

            // 生成事务ID (Connect命令通常使用1.0)
            var transactionId = 1.0;

            Console.WriteLine($"发送Connect命令: app={appName}, tcUrl={tcUrl}, transactionId={transactionId}");

            // 创建并发送Connect命令
            var commandData = RTMPCommandHelper.CreateConnectCommandPacket(appName, tcUrl, options?.FlashVer ?? "FMLE/3.0 (compatible; FMSc/1.0)", transactionId);

            await _networkStream.SendAMF0CommandAsync(commandData, 128, cancellationToken);
        }


        /// <summary>
        /// 仅发送RTMP命令，不等待响应（使用分块协议）
        /// </summary>
        /// <param name="commandData">AMF命令数据（仅载荷部分）</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>发送任务</returns>
        private async Task SendCommandOnlyAsync(byte[] commandData, CancellationToken cancellationToken = default)
        {
            if (_networkStream == null)
            {
                throw new RTMPConnectionException("Network stream is not available.");
            }

            // 使用新的简化分块接口对AMF命令进行分块
            var chunkedMessage = RTMPChunkHelper.ChunkAMF0Command(commandData);

            // 发送分块后的消息
            await _networkStream.WriteAsync(chunkedMessage, 0, chunkedMessage.Length, cancellationToken);

            // 刷新确保数据发送
            await _networkStream.FlushAsync(cancellationToken);
        }


        /// <summary>
        /// 获取下一个事务ID（线程安全）
        /// </summary>
        private double GetNextTransactionId()
        {
            lock (_transactionLock)
            {
                return _nextTransactionId++;
            }
        }

        /// <summary>
        /// 异步创建流（基于回调机制）
        /// </summary>
        /// <param name="onSuccess">成功回调，参数为新创建的流ID</param>
        /// <param name="onError">错误回调，参数为错误信息</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>发送任务</returns>
        public async Task CreateStreamAsync(Action<uint> onSuccess, Action<string>? onError = null, CancellationToken cancellationToken = default)
        {
            ValidateCanStream();

            try
            {
                var transactionId = GetNextTransactionId();
                var callbackKey = CallbackKey.FromTransactionId(transactionId);

                // 注册成功响应回调
                RegisterCallback<CreateStreamResponseMessage>(callbackKey, response =>
                {
                    if (response.IsSuccessResponse)
                    {
                        onSuccess(response.NewStreamId);
                    }
                    else
                    {
                        onError?.Invoke($"CreateStream失败: {response.CommandName}");
                    }
                }, isOneTime: true, timeout: TimeSpan.FromSeconds(10));

                // 创建并发送createStream命令（使用新的命令包接口）
                var commandData = RTMPCommandHelper.CreateCreateStreamCommandPacket(transactionId);
                await SendCommandOnlyAsync(commandData, cancellationToken);
            }
            catch (Exception ex)
            {
                ChangeState(RTMPClientState.Error);
                onError?.Invoke($"发送CreateStream命令失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 异步创建流（返回Task<uint>的兼容版本）
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>创建流任务，返回流 ID</returns>
        public async Task<uint> CreateStreamAsync(CancellationToken cancellationToken = default)
        {
            ValidateCanStream();

            var tcs = new TaskCompletionSource<uint>();
            var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(10));

            // 组合取消令牌
            using var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);

            // 注册取消处理
            combinedCts.Token.Register(() =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    tcs.TrySetCanceled(cancellationToken);
                }
                else if (timeoutCts.Token.IsCancellationRequested)
                {
                    tcs.TrySetException(new TimeoutException("CreateStream操作超时"));
                }
            });

            try
            {
                await CreateStreamAsync(
                    onSuccess: streamId => tcs.TrySetResult(streamId),
                    onError: error => tcs.TrySetException(new RTMPException(error)),
                    cancellationToken
                );

                return await tcs.Task;
            }
            catch (Exception)
            {
                ChangeState(RTMPClientState.Error);
                throw;
            }
        }

        /// <summary>
        /// 异步播放流（基于回调机制）
        /// </summary>
        /// <param name="streamId">流 ID</param>
        /// <param name="streamName">流名称</param>
        /// <param name="onSuccess">成功回调</param>
        /// <param name="onStatus">状态回调，接收播放状态更新</param>
        /// <param name="onError">错误回调</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>发送任务</returns>
        public async Task PlayAsync(uint streamId, string streamName, Action? onSuccess = null, Action<PlayStatusMessage>? onStatus = null, Action<string>? onError = null, CancellationToken cancellationToken = default)
        {
            ValidateCanStream();
            ChangeState(RTMPClientState.Streaming);

            try
            {
                // 注册播放状态回调（基于流ID）
                if (onStatus != null)
                {
                    var statusKey = CallbackKey.FromStreamId(streamId);
                    RegisterCallback<PlayStatusMessage>(statusKey, onStatus, isOneTime: false);
                }

                // 创建并发送play命令（使用新的命令包接口）
                var commandData = RTMPCommandHelper.CreatePlayCommandPacket(streamName);
                await SendCommandOnlyAsync(commandData, cancellationToken);

                Console.WriteLine($"Playing stream: {streamName} with ID: {streamId}");
                onSuccess?.Invoke();
            }
            catch (Exception ex)
            {
                ChangeState(RTMPClientState.Error);
                onError?.Invoke($"发送Play命令失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 异步播放流（兼容版本）
        /// </summary>
        /// <param name="streamId">流 ID</param>
        /// <param name="streamName">流名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>播放任务</returns>
        public Task PlayAsync(uint streamId, string streamName, CancellationToken cancellationToken)
        {
            return PlayAsync(streamId, streamName, null, null, null, cancellationToken);
        }

        /// <summary>
        /// 异步发布流（基于回调机制）
        /// </summary>
        /// <param name="streamId">流 ID</param>
        /// <param name="streamName">流名称</param>
        /// <param name="publishType">发布类型（live/record/append）</param>
        /// <param name="onSuccess">成功回调</param>
        /// <param name="onStatus">状态回调，接收发布状态更新</param>
        /// <param name="onError">错误回调</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>发送任务</returns>
        public async Task PublishAsync(uint streamId, string streamName, string publishType = "live", Action? onSuccess = null, Action<PublishStatusMessage>? onStatus = null, Action<string>? onError = null, CancellationToken cancellationToken = default)
        {
            ValidateCanStream();
            ChangeState(RTMPClientState.Streaming);

            try
            {
                // 注册发布状态回调（基于流ID）
                if (onStatus != null)
                {
                    var statusKey = CallbackKey.FromStreamId(streamId);
                    RegisterCallback<PublishStatusMessage>(statusKey, onStatus, isOneTime: false);
                }

                // 创建并发送publish命令（使用新的命令包接口）
                var commandData = RTMPCommandHelper.CreatePublishCommandPacket(streamName, publishType);
                await SendCommandOnlyAsync(commandData, cancellationToken);

                Console.WriteLine($"Publishing stream: {streamName} with ID: {streamId}");
                onSuccess?.Invoke();
            }
            catch (Exception ex)
            {
                ChangeState(RTMPClientState.Error);
                onError?.Invoke($"发送Publish命令失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 异步发布流（兼容版本）
        /// </summary>
        /// <param name="streamId">流 ID</param>
        /// <param name="streamName">流名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>发布任务</returns>
        public Task PublishAsync(uint streamId, string streamName, CancellationToken cancellationToken)
        {
            return PublishAsync(streamId, streamName, "live", null, null, null, cancellationToken);
        }

        /// <summary>
        /// 异步关闭连接
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>关闭任务</returns>
        public async Task CloseAsync(CancellationToken cancellationToken = default)
        {
            ValidateCanDisconnect();
            ChangeState(RTMPClientState.Disconnecting);

            try
            {
                // 停止消息接收和清理回调组件
                await CleanupComponentsAsync();

                if (_networkStream != null)
                {
                    await _networkStream.DisposeAsync();
                    _networkStream = null;
                }

                if (_tcpClient != null)
                {
                    _tcpClient.Close();
                    _tcpClient = null;
                }

                ChangeState(RTMPClientState.Disconnected);
            }
            catch (Exception)
            {
                ChangeState(RTMPClientState.Error);
                throw;
            }
        }

        /// <summary>
        /// 初始化消息处理组件
        /// </summary>
        private async Task InitializeMessageHandlingAsync(CancellationToken cancellationToken = default)
        {
            lock (_componentsLock)
            {
                if (_networkStream == null)
                {
                    throw new RTMPConnectionException("Network stream is not available.");
                }

                // 创建消息接收器
                _messageReceiver = new NetworkMessageReceiver(_networkStream);

                // 创建回调管理器
                _callbackManager = new CallbackManager(_messageConverter);

                // 订阅消息接收事件
                _messageReceiver.MessageReceived += OnMessageReceived;
            }

            // 启动后台消息接收
            if (_messageReceiver != null)
            {
                await _messageReceiver.StartReceivingAsync(cancellationToken);
            }
        }

        /// <summary>
        /// 清理消息处理组件
        /// </summary>
        private async Task CleanupComponentsAsync()
        {
            IMessageReceiver? receiverToCleanup = null;
            CallbackManager? callbackManagerToCleanup = null;

            lock (_componentsLock)
            {
                receiverToCleanup = _messageReceiver;
                callbackManagerToCleanup = _callbackManager;

                if (_messageReceiver != null)
                {
                    _messageReceiver.MessageReceived -= OnMessageReceived;
                    _messageReceiver = null;
                }

                _callbackManager = null;
            }

            // 在锁外执行清理操作
            if (receiverToCleanup != null)
            {
                try
                {
                    await receiverToCleanup.StopReceivingAsync();
                    receiverToCleanup.Dispose();
                }
                catch
                {
                    // 忽略清理时的异常
                }
            }

            callbackManagerToCleanup?.ClearCallbacks();
        }

        /// <summary>
        /// 处理接收到的消息
        /// </summary>
        private async void OnMessageReceived(object? sender, MessageReceivedEventArgs e)
        {
            CallbackManager? currentCallbackManager;
            lock (_componentsLock)
            {
                currentCallbackManager = _callbackManager;
            }

            if (currentCallbackManager == null) return;

            try
            {
                // 解析消息获取actionID和streamId
                var (actionId, streamId, commandName) = ExtractMessageIdentifiers(e.Payload);

                // 将消息转发给回调管理器处理
                await currentCallbackManager.ProcessMessageAsync(e.Payload, actionId, streamId, commandName);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"消息处理时发生错误: {ex.Message}");
            }
        }

        /// <summary>
        /// 从消息中提取标识符（actionID、streamId、commandName）
        /// </summary>
        private (double actionId, uint streamId, string? commandName) ExtractMessageIdentifiers(byte[] messageData)
        {
            try
            {
                // 尝试解析为命令消息
                var response = RTMPCommandHelper.ParseCommandResponse(messageData);
                return (response.TransactionId, 0, response.CommandName);
            }
            catch
            {
                // 如果解析失败，返回默认值
                return (0, 0, null);
            }
        }

        /// <summary>
        /// 注册强类型消息回调
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="key">回调键</param>
        /// <param name="callback">回调处理器</param>
        /// <param name="isOneTime">是否为一次性回调</param>
        /// <param name="timeout">超时时间</param>
        public void RegisterCallback<T>(CallbackKey key, IMessageCallback<T> callback, bool isOneTime = false, TimeSpan? timeout = null) where T : class
        {
            lock (_componentsLock)
            {
                _callbackManager?.RegisterCallback(key, callback, isOneTime, timeout);
            }
        }

        /// <summary>
        /// 注册委托形式的回调
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="key">回调键</param>
        /// <param name="handler">处理委托</param>
        /// <param name="isOneTime">是否为一次性回调</param>
        /// <param name="timeout">超时时间</param>
        public void RegisterCallback<T>(CallbackKey key, Func<T, CancellationToken, Task> handler, bool isOneTime = false, TimeSpan? timeout = null) where T : class
        {
            lock (_componentsLock)
            {
                _callbackManager?.RegisterCallback(key, handler, isOneTime, timeout);
            }
        }

        /// <summary>
        /// 注册简单委托形式的回调
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="key">回调键</param>
        /// <param name="handler">处理委托</param>
        /// <param name="isOneTime">是否为一次性回调</param>
        /// <param name="timeout">超时时间</param>
        public void RegisterCallback<T>(CallbackKey key, Action<T> handler, bool isOneTime = false, TimeSpan? timeout = null) where T : class
        {
            lock (_componentsLock)
            {
                _callbackManager?.RegisterCallback(key, handler, isOneTime, timeout);
            }
        }

        /// <summary>
        /// 取消注册回调
        /// </summary>
        /// <param name="key">回调键</param>
        /// <returns>是否成功取消</returns>
        public bool UnregisterCallback(CallbackKey key)
        {
            lock (_componentsLock)
            {
                return _callbackManager?.UnregisterCallback(key) ?? false;
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            try
            {
                CloseAsync().GetAwaiter().GetResult();
            }
            catch
            {
                // 忽略释放时的错误
            }
        }
    }
}
